<?php
/*
 * Copyright (c) 2009 Tom Smith (tom@takeontom.com).
 * 
 * Distributed under the terms of the GNU Lesser General Public License.
 * 
 * ---------------------------------------------------------------------------------
 * 
 * This file is part of Seraph PHP Framework.
 *
 * Seraph PHP Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Seraph PHP Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Seraph PHP Framework.  If not, see <http://www.gnu.org/licenses/>.
*/


class EntityDAO	{
	
	/**
	 * 
	 * @param $entity
	 * @return bool
	 */
	public function insert(Entity $entity)	{
		$db = $entity->getDatabase();
		$insertSQL = $db->generateInsertStatementSQL($entity->getTableName(), $entity->getEntityData());
		
		$res = $db->query($insertSQL);
		
		if (!$res->isSuccess())	{
			throw new RuntimeException('Entity insert failed for the following reason: ' . $res->getErrorMessage());
			return false;
		}
		
		$entity->setInsertID($res->getLastInsertID());

		return true;
	}
	
	/**
	 * 
	 * @param $entity
	 * @return bool
	 */
	public function update(Entity $entity)	{
		$db = $entity->getDatabase();
		
		foreach($entity->getModifiedColumns() as $col => $v)	{
			$values[$col] = $entity->$col;
		}
		
		$key = $entity->getPrimaryKeyValue();
		
		if (!$entity->isPrimaryKeySet())	{
			throw new RuntimeException('Can not update entity until all primary key columns have been given values');
			return false;
		}
		
		$updateSQL = $db->generateUpdateStatementSQL($entity->getTableName(), $values, $key);
		
		$res = $db->query($updateSQL);
		
		if (!$res->isSuccess())	{
			throw new RuntimeException('Entity update failed for the following reason: ' . $res->getErrorMessage());
			return false;
		}
		return true;
	}
	
	public function delete(Entity $entity)	{
		$db = $entity->getDatabase();
		if (!$entity->isPrimaryKeySet())	{
			throw new RuntimeException('Can not delete entity until all primary key columns have been given values');
			return false;
		}
		
		$deleteSQL = $db->generateDeleteStatementSQL($entity->getTableName(), $entity->getPrimaryKeyValue());
		
		$res = $db->query($deleteSQL);
		
		if (!$res->isSuccess())	{
			throw new RuntimeException('Entity delete failed for the following reason: ' . $res->getErrorMessage());
			return false;
		}
		return true;
	}
	
	/**
	 * Load an entity from the database.
	 * 
	 * Will return the completed entity.
	 * 
	 * On failure will return false.
	 *  
	 * @param $key
	 * @return Entity | EntityContainer
	 */
	public function get(Entity $entity, array $key)	{
		
		$db = $entity->getDatabase();
		$selectSQL = $db->generateSelectSQLStatement($entity->getTableName(), $key);
		
		$res = $db->query($selectSQL);
		
		if (!$res->isSuccess())	{
			throw new RuntimeException('Entity get operation failed for the following reason: ' . $res->getErrorMessage());
			return false;
		}
		
		//work out whether we're expecting a single result (i.e. are we querying my a primary key?
		//for primary key matches, return a single entity
		//for other matches, return an EntityContainer, regardless of the number of results.
		if ($entity->doesPrimaryKeyMatch(array_keys($key)))	{
			//ensure that we've only got one result
			if (count($res) > 1)	{
				throw new RuntimeException('Entity get operation failed. Got more than one (' . count($res) . ') result');
				return false;
			}
			if (count($res) == 1)	{
				$entity->setEntityData($res[0]);
				return $entity;
			}
		} else {
			$c = new EntityContainer();
			$class = get_class($entity);
			foreach($res as $aRes)	{
				$newE = new $class;
				$newE->setEntityData($aRes);
				$c->addEntity($newE);
			}
			return $c;
		}
		
		
		//not found
		return false;
	}
}
?>